﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2013  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#ifndef _UXS_GLES_RENDER_STATE_H
#define _UXS_GLES_RENDER_STATE_H

#include "GLESCommon.h"

namespace UX_STL
{
namespace GLESshell
{
	
	namespace e_color_mask
	{
		enum	type	: uint8
		{
			NONE	= 0,

			R		= 0x01,
			G		= 0x02,
			B		= 0x04,
			A		= 0x08,
			RGBA	= R | G | B | A,

			RG		= R | G,
			RB		= R | B,
			RGB		= R | G | B,
			GB		= G | B,
			GA		= G | A,
			GBA		= G | B | A,
			BA		= B | A,
		};

		UX_ENUM_BIT_OPERATIONS( type )
	}



	//
	// Render State
	//

	class GLESRenderState //: public GLESBaseObject
	{
	public:
		struct TColorBuffer
		{
			gl_blend_func::type		eSrcRGB,
									eSrcAlpha,
									eDstRGB,
									eDstAlpha;
			gl_blend_equation::type	eModeRGB,
									eModeAlpha;
			e_color_mask::type		eMask;
			bool					bBlending;
			///
			TColorBuffer():
				bBlending(false),						eMask(e_color_mask::RGBA),
				eSrcRGB(gl_blend_func::ONE),			eSrcAlpha(gl_blend_func::ONE),
				eDstRGB(gl_blend_func::ZERO),			eDstAlpha(gl_blend_func::ZERO),
				eModeRGB(gl_blend_equation::ADD),		eModeAlpha(gl_blend_equation::ADD)
			{}
		};

		struct TStencilState
		{
			struct TSide
			{
				gl_stencil_op::type		eSFail,		// stencil test fail
										eDFail,		// stencil tess passes, but depth test fail
										eDPPass;	// stencil test and depth test pass
				gl_compare::type		eFunc;		// (ref & mask) op (stencil & mask)
				uint8					uFuncRef;
				uint8					uFuncMask;
				uint8					uMask;
				///
				TSide():
					eSFail(gl_stencil_op::KEEP),	eDFail(gl_stencil_op::KEEP),
					eDPPass(gl_stencil_op::KEEP),	eFunc(gl_compare::ALWAYS),
					uFuncRef(0),	uFuncMask(-1), uMask(-1)
				{}
			};

			static_array<TSide,2>	aSide;	// front, back
			bool					bTest;
			///
			TStencilState(): bTest(false) {}
		};

		struct TDepthState
		{
			gl_compare::type		eFunc;
			bool					bWrite;
			bool					bTest;
			///
			TDepthState(): eFunc(gl_compare::LEQUAL), bWrite(true), bTest(true) {}
		};

		struct TCullState
		{
			gl_face::type			eCullFace;
			gl_front_face::type		eFrontFace;
			bool					bCullFace;
			///
			TCullState():
				eCullFace(gl_face::BACK), eFrontFace(gl_front_face::CCW), bCullFace(false)
			{}
		};

		struct TStates
		{
			float					fSampleCoverage;
			bool					bInvertSampleCoverage;
			bool					bDither,
									bPolygonOffset,
									bAlphaToCoverage,
									bSampleCoverage;
			///
			TStates():
				bDither(false), bPolygonOffset(false), bAlphaToCoverage(false),
				bSampleCoverage(false), bInvertSampleCoverage(false),
				fSampleCoverage(1.0f)
			{}
		};


		TColorBuffer					sColorBuffer;
		TStencilState					sStencil;
		TDepthState						sDepth;
		TStates							sStates;
		TCullState						sCull;
		vec2							vPolygonOffset;
		///
		GLESRenderState() {}
		
		void Validate();
	};
	
//-------------------------------------------------------------------

}	// GLESshell
}	// UX_STL

#endif	// _UXS_GLES_RENDER_STATE_H